#ifndef __CANQUENE_H
#define __CANQUENE_H

#include <stdint.h>
#include "mytype.h"
#include "dataproc.h"

#ifdef __cplusplus
extern "C"
{
#endif

	enum simp_can_snd_st_type
	{
		SIMP_CAN_TX_IDLE = 0,
		SIMP_CAN_TX_BUSY = 1,
		SIMP_CAN_TX_WAIT_TE = 2,
	};

#define SIMP_CAN_ID_MODE_STD 0
#define SIMP_CAN_ID_MODE_EXT 1

#define SIMP_CAN_ID_MASK 0x1FFFFFFFUL
#define SIMP_CAN_ACKID_MASK 0x1FFFFFF8UL

	typedef struct
	{
		uint32_t id;
		uint8_t id_mode;
		uint8_t remot;
		uint8_t len;
		word_tt dat[4];
	} simp_can_frame_type;

	typedef struct
	{
		uint32_t id : 30; 
		uint32_t id_mode : 1;
		uint32_t remot : 1;
		uint16_t sub_addr;
		uint16_t len;
		void *dat;
	} simp_can_cmd_type;

	struct simp_can_frame_ctr_str
	{
		volatile uint16_t tx_site_fill; 
		uint16_t tx_site_send;			

		volatile uint16_t tx_rt_site_fill; 
		uint16_t tx_rt_site_send;		   

		volatile uint16_t rx_site_rcv; 
		uint16_t rx_site_read;		   

		volatile enum simp_can_snd_st_type tx_st; 

		uint16_t tx_idle_time_cnt;	
		uint16_t tx_frame_time_cnt; 
		uint16_t tx_act_time_cnt;	
		uint16_t rx_idle_time_cnt;	
		uint16_t hal_idle_time_cnt; 

		uint32_t tx_cnt;
		uint32_t rx_cnt;

		uint16_t tx_buff_amount;
		uint16_t tx_rt_buff_amount;
		uint16_t rx_buff_amount;
		simp_can_frame_type *rx_frame;
		simp_can_frame_type *tx_frame;
		simp_can_frame_type *tx_rt_frame;
		void (*tx_send)(simp_can_frame_type *); 
		void (*rx_handle)(simp_can_frame_type *);
		uint8_t (*is_tx_hal_empty)(void);
		uint8_t (*is_tx_hal_full)(void);

		uint16_t cmd_exe_time_interval; 
		uint16_t os_event_req;
		uint8_t cmd_stc_site_exe; 
		uint8_t cmd_stc_amount;
		uint8_t cmd_sync_site_exe;	
		uint8_t cmd_sync_site_fill; 
		uint8_t cmd_sync_amount;
		uint8_t cmd_exe_mode; 
		uint8_t ack_master;
		uint8_t ack_err_cnt;
		uint16_t ack_rcv_cnt;
		uint32_t ack_id_start;
		uint32_t ack_id_mask; 
		uint32_t ack_id_comp; 
		void (*cmd_handle_callback)(uint8_t err_st, struct simp_can_frame_ctr_str *quene);
		void (*os_event_send)(uint16_t event);
		simp_can_cmd_type *stc_cmd_buff;
		simp_can_cmd_type *sync_cmd_buff;
		simp_can_cmd_type cmd_exe_now;
	};

	typedef struct simp_can_frame_ctr_str simp_can_frame_ctr_type;

#define SIMP_CAN_EXE_MODE_STC 0
#define SIMP_CAN_EXE_MODE_SYNC 1
#define SIMP_CAN_EXE_MODE_SYNC_ACK 2
#define SIMP_CAN_EXE_MODE_SYNC_ACK_OK 3
#define SIMP_CAN_EXE_MODE_SYNC_ACK_ERR 0x80
#define SIMP_CAN_EXE_MODE_SYNC_ACK_TIMEOUT 0x81

#define SIMP_CAN_EXE_MODE_ERR_MARK 0x80

#define SIMP_CAN_OS_EVENT_INTERVAL 0x01
#define SIMP_CAN_OS_EVENT_RCV 0x02
#define SIMP_CAN_OS_EVENT_ACK_TIMEOUT 0x04
#define SIMP_CAN_OS_EVENT_SYNC_CMD_RDY 0x08
#define SIMP_CAN_OS_EVENT_SYNC_CMD_NOUSE 0x10

#define SPMP_CAN_POLL_ID_MODE 0
#define SPMP_CAN_POLL_SDAT_MODE 1

	void simp_can_poll(simp_can_frame_ctr_type *ctr);

	enum simp_can_snd_st_type simp_can_transmit(simp_can_frame_ctr_type *ctr);

	uint8_t simp_can_send(simp_can_frame_ctr_type *ctr, simp_can_frame_type *frame);

	uint8_t simp_can_rt_send(simp_can_frame_ctr_type *ctr, simp_can_frame_type *frame);

	uint8_t simp_can_receive(simp_can_frame_ctr_type *ctr, simp_can_frame_type *frame);

	uint16_t simp_can_tx_buff_used_amount(simp_can_frame_ctr_type *ctr);

	uint16_t simp_can_tx_buff_remain_amount(simp_can_frame_ctr_type *ctr);

	uint16_t simp_can_tx_rt_buff_used_amount(simp_can_frame_ctr_type *ctr);

	uint16_t simp_can_tx_rt_buff_remain_amount(simp_can_frame_ctr_type *ctr);

	void simp_can_time_run(simp_can_frame_ctr_type *ctr);

	void simp_can_cmd_init(
		simp_can_frame_ctr_type *quene,
		simp_can_cmd_type *stc_cmd_buff,
		uint8_t stc_cmd_amount,
		simp_can_cmd_type *sync_cmd_buff,
		uint8_t sync_cmd_amount);

	uint8_t simp_can_stc_cmd_req(
		simp_can_frame_ctr_type *quene,
		uint8_t cmd_site,
		simp_can_cmd_type *cmd);

	uint8_t simp_can_stc_cmd_del(
		simp_can_frame_ctr_type *quene,
		uint8_t cmd_site);

	uint8_t simp_can_sync_cmd_req(
		simp_can_frame_ctr_type *quene,
		simp_can_cmd_type *cmd);

	uint16_t simp_can_sync_cmd_used_amount(simp_can_frame_ctr_type *ctr);

	uint16_t simp_can_sync_cmd_remain_amount(simp_can_frame_ctr_type *ctr);

	uint8_t simp_can_cmd_exe(
		simp_can_frame_ctr_type *quene,
		simp_can_cmd_type *cmd,
		uint8_t cmd_mode);

	uint8_t simp_can_sdat_cmd_exe(
		simp_can_frame_ctr_type *quene,
		simp_can_cmd_type *cmd,
		uint8_t cmd_mode);

	void simp_can_cmd_poll_mute(simp_can_frame_ctr_type *quene, char mode);

	void simp_can_cmd_poll_ack(simp_can_frame_ctr_type *quene);
	void simp_can_cmd_slave_ack_id(
		simp_can_frame_ctr_type *quene,
		uint32_t mask,
		uint32_t comp);

	typedef struct
	{
		uint8_t sjw_max;		   
		uint8_t bs1_max;		   
		uint8_t bs2_max;		   
		uint8_t bs_min;			   
		uint8_t sample_point_set;  
		uint8_t sample_point_rang; 
		uint16_t div_max;		   
		uint32_t clk;			   
		uint32_t baud_set;		   

		uint32_t baud_back;			 
		uint8_t sample_point_back;	 
		uint16_t div, sjw, bs1, bs2; 
	} can_baud_cal_type;
	void can_buad_cal(can_baud_cal_type *cbaud);

#ifdef __cplusplus
}
#endif

#endif 
